/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package nl.unimaas.games.tron.player.mcts;

import nl.unimaas.games.tron.engine.Board;

/**
 *
 * @author Cliff
 */
public class SolverNode extends Node {

    public double pess, opti;
    public boolean proven = false;

    public boolean isProvenWin() {
        return (proven && pess == 1);
    }

    public boolean isProvenDraw() {
        return (proven && pess == 0);
    }

    public boolean isProvenLoss() {
        return (proven && opti == -1);
    }

    /** @return minimum number of steps needed to win */
    public int getWinSteps() {
        if (!isProvenWin()) {
            throw new IllegalStateException("win???");
        }

        int minSteps = Integer.MAX_VALUE, steps;
        if (children.isEmpty()) {
            minSteps = 0;
        } else {
            SolverNode n;
            for (int i = children.size(); --i >= 0;) {
                n = ((SolverNode) children.get(i));
                if (n.isProvenWin()) {
                    steps = n.getWinSteps();
                    if (steps < minSteps) {
                        minSteps = steps;
                    }
                }
            }
        }
        return minSteps + 1;
    }

    public SolverNode(int playerNr, boolean max) {
        super(playerNr, max);
        init();
    }

    public SolverNode(SolverNode parent, int playerNr, int move, boolean max, Board b) {
        super(parent, playerNr, move, max, b);
        init();
    }

    private void init() {
        pess = -1;
        opti = 1;
    }

    public boolean checkIfProven() {
        if (isRoot()) {
            return false;
        }
        proven = (pess == opti);
        if (!proven) {
            for (int i = 0; i < children.size(); i++) {
                if (!((SolverNode) children.get(i)).proven) {
                    return false;
                }
            }
        }
        proven = true;
        return proven;
    }

    @Override
    public String toString() {
        return String.format("node[id=%d, move=%s, player=%d, visits=%d, wins=%.1f%% (%d), draws=%.1f%% (%d), value=%.2f, children=%d, proven=%s (pess=%.0f, opti=%.0f)]", id, Board.moveToString(move), playerNr, visits, wins / (float) visits * 100, wins, draws / (float) visits * 100, draws, value, children.size(), Boolean.toString(proven), pess, opti);
    }
}
